#ifndef __H_ANY__
#define __H_ANY__

#include <typeinfo>

namespace bl{


	class any
	{
	public:

		any() : content_(0) {}

		template<typename ValueType>
		any(const ValueType& value) : content_(new Holder<ValueType>(value))	{}

		any(const any& other) : content_(other.content_ ? other.content_->clone() : 0) {}

		~any()
		{
			delete content_;
		}


	public:

		any& swap(any& rhs)
		{
			std::swap(content_, rhs.content_);
			return *this;
		}

		template<typename ValueType>
		any& operator=(const ValueType& rhs)
		{
			any(rhs).swap(*this);
			return *this;
		}

		any& operator=(any rhs)
		{
			rhs.swap(*this);
			return *this;
		}

		bool empty() const
		{
			return !content_;
		}

		const std::type_info& type() const
		{
			return content_? content_->type() : typeid(void);
		}

	private:

		class PlaceHolder
		{
		public:
			virtual ~PlaceHolder() {}

			virtual const std::type_info& type() const = 0;
			virtual PlaceHolder* clone() const = 0;
		};

		template<typename ValueType>
		class Holder: public PlaceHolder
		{
		public:
			Holder(const ValueType& val) : held_(val) {}

			virtual const std::type_info& type() const
			{
				return typeid(ValueType);
			}

			virtual PlaceHolder* clone() const
			{
				return new Holder(held_);
			}

			ValueType held_;

		private:
			Holder& operator=(const Holder&);
		};

	private:

		template<typename ValueType>
		friend ValueType* any_cast(any *);
		
		template<typename ValueType>
		friend ValueType* unsafe_any_cast(any *);

		PlaceHolder* content_;
	};

	template<typename ValueType>
	ValueType* any_cast(any* operand)
	{
		return (operand && operand->type()==typeid(ValueType)) ? &static_cast<any::Holder<ValueType>*>(operand->content_)->held_ : 0;
	}

	template<typename ValueType>
	inline const ValueType* any_cast(const any* operand)
	{
		return any_cast<ValueType>(const_cast<any*>(operand));
	}

	template<typename ValueType>
	ValueType any_cast(any& operand)
	{
		ValueType* res = any_cast<ValueType>(&operand);
		return *res;
	}

	template<typename ValueType>
	inline ValueType any_cast(const any& operand)
	{
		return any_cast<const ValueType&>(const_cast<any&>(operand));
	}

	template<typename ValueType>
	inline ValueType* unsafe_any_cast(any* operand)
	{
		return &static_cast<any::Holder<ValueType> *>(operand->content_)->held_;
	}

	template<typename ValueType>
	inline const ValueType* unsafe_any_cast(const any* operand)
	{
		return unsafe_any_cast<ValueType>(const_cast<any*>(operand));
	}


}


#endif